package com.tianji.learning.task;

import com.tianji.common.utils.CollUtils;
import com.tianji.learning.constants.LearningConstants;
import com.tianji.learning.constants.RedisConstants;
import com.tianji.learning.domain.po.PointsBoard;
import com.tianji.learning.domain.po.PointsBoardSeason;
import com.tianji.learning.service.IPointsBoardSeasonService;
import com.tianji.learning.service.IPointsBoardService;
import com.tianji.learning.service.IPointsRecordService;
import com.tianji.learning.util.TableInfoContext;
import com.xxl.job.core.context.XxlJobHelper;
import com.xxl.job.core.handler.annotation.XxlJob;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.data.redis.core.StringRedisTemplate;
import org.springframework.stereotype.Component;

import java.time.LocalDate;
import java.time.format.DateTimeFormatter;
import java.util.List;

@Slf4j
@Component
@RequiredArgsConstructor
public class PointsBoardPersistentHandler {

    private final IPointsBoardSeasonService boardSeasonService;

    private final IPointsBoardService boardService;

    private final StringRedisTemplate redisTemplate;

    /**
     * 创建历史赛季排行表
     */
    @XxlJob("createTableJob")
    public void createPointsBoardTableOfLastSeason() {
        log.info("=====创建表任务执行=====");
        //1.获取上个月的时间点
        LocalDate beforeMonth = LocalDate.now().minusMonths(1);
        //2.查询赛季，获取赛季id，赛季id就是表的版本
        //开始时间小于上个月 结束时间大于上个月
        PointsBoardSeason one = boardSeasonService.lambdaQuery()
                .le(PointsBoardSeason::getBeginTime, beforeMonth)
                .ge(PointsBoardSeason::getEndTime, beforeMonth)
                .one();
        log.info("上赛季信息: {}", one);
        if (one == null) {
            return;
        }
        //3.创建表
        boardSeasonService.createPointsBoardLatestTable(one.getId());
    }

    /**
     * 持久化上赛季的榜单
     */
    @XxlJob("savePointsBoard2DB")
    public void savePointsBoard2DB() {
        log.info("=======开始持久化上赛季的榜单=======");
        //1.获取上个月的时间点
        LocalDate now = LocalDate.now().minusMonths(1);
        //2.查询上个赛季信息
        PointsBoardSeason one = boardSeasonService.lambdaQuery().le(PointsBoardSeason::getBeginTime, now)
                .ge(PointsBoardSeason::getEndTime, now)
                .one();
        if (one == null) {
            return;
        }
        //3.计算表名
        String tableName = LearningConstants.POINT_BOARD_TABLE_PREFIX + one.getId();
        TableInfoContext.setInfo(tableName);
        //4.分页获取redis中的数据
        String format = now.format(DateTimeFormatter.ofPattern("yyyyMM"));
        String key = RedisConstants.POINTS_BOARD_KEY_PREFIX + format;//获取key
        int shardIndex = XxlJobHelper.getShardIndex();
        int shardTotal = XxlJobHelper.getShardTotal();
        int pageNo = shardIndex + 1;
        int pageSize = 5;
        log.info("=======开始存表=======");
        while (true) {
            log.info("处理第{}页数据", pageNo);
            List<PointsBoard> boardList = boardService.queryCurrentBoard(key, pageNo, pageSize);
            if (CollUtils.isEmpty(boardList)) {
                break;
            }
//            pageNo++;
            pageNo += shardTotal;
            //5.持久化
            for (PointsBoard board : boardList) {
                board.setId(Long.valueOf(board.getRank()));
                board.setRank(null);
            }
            boardService.saveBatch(boardList);
        }
        //6.清空ThreadLocal
        log.info("=======存表完毕=======");
        TableInfoContext.remove();
    }

    /**
     * 清除Redis中上赛季榜单
     */
    @XxlJob("clearPointsBoardFromRedis")
    public void clearPointsBoardFromRedis() {
        //1.获取上月时间
        LocalDate time = LocalDate.now().minusMonths(1);
        //2.计算key
        String format = time.format(DateTimeFormatter.ofPattern("yyyyMM"));
        String key = RedisConstants.POINTS_BOARD_KEY_PREFIX + format;
        //清除
        redisTemplate.unlink(key);
    }

}
